#!/usr/bin/env python

# FacebookGroupDownloader is part of code.google.com/camtools, copyright
# 2008-2015 Camille Huot and is licensed under
# http://www.gnu.org/copyleft/gpl.html

# FacebookGroupDownloader will download the full post/comment history that is
# readable at the moment of the script execution and product 2 files:
# - a JSON file containing the exact data returned by Facebook 
# - a simple HTML version containing all the posts and comments of the group
# from the creation date, on a single page

# You need to provide the Facebook Graph ID of the group. For example:
# - The URL for the Bitcoin Developers Guild is
#   https://www.facebook.com/groups/907345989276086/
# - The ID is 907345989276086

# You also need an Access Token from Facebook. You can get one at this URL:
# https://developers.facebook.com/tools/explorer
# By loging and clicking "Get Access Token"

_VERSION = 1

import json, urllib.request, datetime, re, os

print('FacebookGroupDownloader V.{} - Camille Huot - camille@huot.name'.format(_VERSION))
print('')
GRAPH_OBJID = input('Enter the Graph ID of the group you wish to backup (or ALL): ')
FB_TOKEN = input("Now enter your access token.\nYou can grab one at this URL by clicking \"Get Access Token\"\nhttps://developers.facebook.com/tools/explorer\n> ")

URL = "https://graph.facebook.com/{}/feed?access_token={}&limit=10000"
TODAY = datetime.datetime.now().strftime("%Y%m%d")

def DL(GRAPH_OBJID):
 gname = ''
 print('Saving the entire history of this Facebook Group {}'.format(GRAPH_OBJID))
 f = open('tmpfile.fbdl','w')
 f.write('[')
 
 url = URL.format(GRAPH_OBJID, FB_TOKEN)
 while url:
  print('*')
  res = urllib.request.urlopen(url)
  text = res.read().decode('utf8')
  f.write(text + ',')
  feed = json.loads(text)
  
  if gname == '':
   gname = feed['data'][0]['to']['data'][0]['name']
   gname = re.sub('[^0-9a-zA-Z]+', '_', gname)
  if 'paging' in feed and 'next' in feed['paging']:
   url = feed['paging']['next']
  else:
   url = None
 
 f.seek(max(3, f.tell())-1)
 f.write(']')
 f.close()
 os.rename('tmpfile.fbdl', '{}-{}.json'.format(TODAY, gname))
 print('Downloading done.')
 print('')
 htmlfilename = '{}-{}.html'.format(TODAY, gname)
 print('Converting the data to HTML ({})...'.format(htmlfilename))
 
 f=open('{}-{}.json'.format(TODAY, gname))
 data=json.loads(f.read())
 f.close()
 f=open(htmlfilename, 'w')
 f.write('<dl>\n')
 for page in data:
  for post in page['data']:
   who = post['from']['name']
   date = post['created_time']
   if 'message' in post:
    msg = post['message']
   else:
    msg = '(NO MESSAGE)'
   f.write('<dt>{} - {}</dt><dd>{}<dl>\n'.format(who, date, msg))
   if 'comments' in post:
    for com in post['comments']['data']:
     who = com['from']['name']
     msg = com['message']
     date = com['created_time']
     f.write('<dt>{} - {}</dt><dd>{}</dd>\n'.format(who, date, msg))
   f.write('</dl></dd>\n')
 f.write('</dl>\n')
 f.close()
 print('Group downloaded')

if GRAPH_OBJID == 'ALL':
 print('Downloading ALL your groups, this can take a long time, consume a lot of space and Facebook can block you...')
 print('Fetching groups...')
 url = 'https://graph.facebook.com/v2.2/me?fields=groups&access_token={}'.format(FB_TOKEN)
 res = urllib.request.urlopen(url)
 text = res.read().decode('utf8')
 gdata = json.loads(text)
 for g in gdata['groups']['data']:
  print('Fetching group {} ({})...'.format(g['id'], g['name']))
  DL(g['id'])
else:
 DL(GRAPH_OBJID)
